// components/pageView/pageView.js
Component({
  /**
   * 组件的属性列表
   */
  properties: {
    // 每页数据量,默认:10
    pageLimit: {
      type: Number,
      value: 10
    },
    // 排序关键字,默认:created_at
    pageSort: {
      type: String,
      value: "created_at"
    },
    // 滚动对应位置,默认:0
    top: {
      type: String,
      value: 0
    },
    // 滚动对应位置,默认:0
    scrollTop: {
      type: Number,
      value: 0
    },
    // 是否能刷新 
    isEnableRefresh: {
      type: Boolean,
      value: true
    },
    // 是否需要显示加载更多
    isShowMoreText: {
      type: Boolean,
      value: true
    },
    // 是否能加载更多
    isCanLoadMore: {
      type: Boolean,
      value: true
    },
    // 滚到顶部距离
    scrollTop: {
      type: Number,
      value: 0
    },
    // 注入页面对象名()
    parentTargetInjectionObjectName: {
      type: String,
      value: undefined
    },
    // 结果解构出list层
    // 例子: {data: {list: [{name:"公司名称"}]}}
    listPath: {
      type: String,
      value: "data.data.list"
    },
    // 请求方法一: 在父界面上定义pageViewId + 'readyRequest'方法,通过方法回调的params参数,重构请求地址
    // 组件内部请求工具: wx.request
    /**
     *  例子: 
     *  //父界面定义pageVieReadyRequest方法(对应组件ID,默认pageVieReadyRequest)
     *  pageVieReadyRequest(params) {
     *    params.url = "https://mall.ggdzhj.com/api/business/product/queryForList"
     *    return params
     *  }
     */

    // 请求方法二: 请求地址 
    // 组件内部请求工具, 默认:wx.request
    /** 
     * 例子: 
     * <pageView requestUrl="https://mall.ggdzhj.com/api/business/product/queryForList" requestUrlMethod="POST"></pageView>
     */
    // 请求地址
    requestUrl: {
      type: String,
      value: ""
    },
    // 请求方法
    requestUrlMethod: {
      type: String,
      value: "POST" // 请求方法对应wx.request
    },
    /** 
     * 请求方法三: 请求方法名称(结合AKHttp使用, 名称定义在/api/api.js)
     * 组件内部请求工具: AKHttp
     * 
     * 例子:
     * <pageView requestMethodName="queryForList"></pageView>
     */
    // 请求方法名称
    requestMethodName: {
      type: String,
      value: "",
      observer: function () {
        if (this.data.isReady == false) return
        this.initInjection(getCurrentPages()[getCurrentPages().length - 1])
      }
    },

  },

  /**
   * 组件的初始数据
   */
  data: {
    // 组件是否加载完成
    isReady: false,
    //是否加载中
    isLoading: false,
    //是否没有更多内容
    isNoMore: false,
    //是否刷新中
    isRefreshing: false
  },

  /**
   * 组件的方法列表
   */
  ready() {
    // 方式一: 自动注入: 注入父界面方法, 对应 "组件Id + ReadyRequest/RequestSuccess/RequestFail" 
    // 方式二: 自定义初始化: 父界面重写初始化方法"init+组件ID", 默认:initPageView

    // 初始化数据
    this.curPage = 1
    this.listCount = 0
    this.list = []
    const pageViewId = this.id || 'pageView'
    this.id = pageViewId
    // 获取当前页面对象
    const parentTarget = getCurrentPages()[getCurrentPages().length - 1]
    parentTarget[pageViewId + "Target"] = this
    // 更新父组件的注入pageView对象
    this.resetInjectionTarget()
    const initFunctionName = 'init' + pageViewId.split("")[0].toUpperCase() + pageViewId.substr(1)
    // 检查父界面是否存在自定义初始化方法, 默认 initPageView
    if (parentTarget[initFunctionName]) {
      parentTarget[initFunctionName](this)
    } else {
      //初始化-注入父控件
      this.initInjection(parentTarget)
    }

    this.setData({
      isReady: true
    })
  },


  methods: {
    // ======================  初始化  ======================
    //初始化-注入父控件
    initInjection(parentTarget) {
      const pageViewId = this.id || 'pageView'
      this.id = pageViewId
      // 注入参数
      const injectionParam = {}
      // 注入统一对象
      const parentTargetInjectionObjectName = this.data.parentTargetInjectionObjectName
      if (parentTargetInjectionObjectName) {
        // 注入对象
        const injectionObject = parentTarget.data[parentTargetInjectionObjectName] ? parentTarget.data[parentTargetInjectionObjectName] : {}
        injectionObject[pageViewId + 'Target'] = this
        injectionParam[parentTargetInjectionObjectName] = injectionObject
        parentTarget.setData(injectionParam)
      } else {
        // 注入对象
        injectionParam[pageViewId + 'Target'] = this
        parentTarget.setData(injectionParam)
      }

      // 注入方法提示
      // if(!parentTarget[pageViewId + 'ReadyRequest']) console.log("组件pageView的父组件页面,可定义方法" + pageViewId + 'ReadyRequest')
      // if(!parentTarget[pageViewId + 'RequestSuccess']) console.log("组件pageView的父组件页面,可定义方法" + pageViewId + 'RequestSuccess')

      // 请求方法
      let httpTool = wx.request
      // 存在AKHttp封装请求名称
      if (this.data.requestMethodName) {
        // #可替换为对应自己的请求封装
        httpTool = wx.$AKHttp[this.data.requestMethodName]
        if (!httpTool) {
          throw "PageView定义的requestMethodName外部变量 [" + this.data.requestMethodName + "], 在api.js中没有定义 方法"
        }
      }

      this.init({
        http: httpTool,
        callReadyRequest: parentTarget[pageViewId + 'ReadyRequest'],
        callSuccess: parentTarget[pageViewId + 'RequestSuccess'],
        callFail: parentTarget[pageViewId + 'RequestFail'],
      })

      // 发起首次请求
      this.refresh()
    },

    // 组成分页基础参数
    initParams(pageLimit, curPage, pageSort) {
      const id = this.id
      // 方法一: 微信自带参数
      const wxRequestParams = {
        method: this.data.requestUrlMethod || "POST",
        url: this.data.requestUrl, //仅为示例，并非真实的接口地址
        data: { //(修改) data根据自身接口
          "pager": {
            "currentPage": curPage, // 当前页,组件内部管理不需要修改
            "pageSize": pageLimit // 每页数量
          },
          "sortPointer": {
            "order": "DESC",
            "field": pageSort //排序
          }
        },
        success: res => {
          this.requestSuccess(res, id)
        },
        fail: ({errMsg, errno}) => {
          this.requestFail(errMsg, errno)
        }
      }
      // 方法二: 自定义AKHttp工具自带参数
      //(修改) 根据自身接口参数
      const akHttpRequestParams = {
        "pager": {
          "currentPage": curPage, // 当前页,组件内部管理不需要修改
          "pageSize": pageLimit // 每页数量
        },
        "sortPointer": {
          "order": "DESC",
          "field": pageSort // 排序
        }
      }
      // 判断是否自定义请求工具
      return this.httpTool == wx.request ? wxRequestParams : akHttpRequestParams
    },


    // 初始化组件属性
    init({
      http,
      callReadyRequest,
      callSuccess,
      callFail
    }) {
      // 判断是否存在http,否则用wx.request
      this.httpTool = http || wx.request
      //判断是否函数或者undefined
      if (this.isFuntionOrUndefined(callReadyRequest)) {
        this.callReadyRequest = callReadyRequest ? callReadyRequest : (params) => params
      }
      //判断是否函数或者undefined
      if (this.isFuntionOrUndefined(callSuccess)) {
        this.callSuccess = callSuccess ? callSuccess : () => {}
      }
      //判断是否函数或者undefined
      if (this.isFuntionOrUndefined(callFail)) {
        this.callFail = callFail ? callFail : () => {}
      }
    },




    // ======================  核心功能  ======================
    //发出请求
    requestList() {
      const httpTool = this.httpTool
      const id = this.id
      if (!httpTool) {
        throw "PageView定义的requestMethodName外部变量 [" + this.data.requestMethodName + "], 在api.js中没有定义 方法"
      }
      // 初始化基础请求参数
      let baseParams = this.initParams(this.data.pageLimit, this.curPage, this.data.pageSort)
      // 调用父组件方法, 可修改请求前参数
      let params = this.callReadyRequest(baseParams, id) || baseParams
      this.triggerEvent("readyRequest", {
        params,
        id
      })
      // 根据请求工具-发起请求
      if (httpTool == wx.request) {
        // 微信回调方法对应->组件initParams方法
        httpTool(params)
      } else {
        httpTool(params).then(res => {
          this.requestSuccess(res, id)
        }, err => {
          this.requestFail(err)
        })
      }
    },



    // ======================  触发方法  ======================
    // 下拉刷新
    refresh() {
      if (this.data.isRefreshing) return
      console.log(this.id + ' 下拉刷新')
      this.curPage = 1
      this.setData({
        scrollTop: 0,
        isNoMore: false
      })
      setTimeout(() => {
        this.setData({
          isRefreshing: false
        })
      }, 300)

      this.setData({
        //是否加载中
        isLoading: true,
      })
      // 发起请求
      this.requestList()
    },

    //上拉加载更多
    scrolltolower() {

      const {
        isLoading,
        isNoMore,
        isCanLoadMore
      } = this.data
      if (isLoading || isNoMore || !isCanLoadMore) {
        return
      }
      this.curPage = this.curPage + 1
      this.setData({
        //是否加载中
        isLoading: true,
      })
      this.requestList()
    },

    // 点击加载更多
    clickMore() {
      this.scrolltolower()
    },

    // 滚动监听
    bindscroll(e) {
      const {
        scrollTop,
        scrollHeight
      } = e.detail

      this.triggerEvent("scrollTop", {
        top: scrollTop,
        height: scrollHeight
      })
    },


    // ======================  功能方法  ======================
    // 请求 成功回调
    requestSuccess(res, id) {
      // 请求成功回调
      res = this.callSuccess(res, id) || res
      // 通过监听事件回调resetResultFun修改结果
      this.triggerEvent("requestSuccess", {
        res,
        id,
        resetResultFun: (newRes) => {
          res = newRes
        }
      })
      const list = this.getResponseList(res)
      // 获取特定参数
      this.updateSpecifyData(res)
      // 更新组件数据
      this.updateDate(list, res.data && res.data.total)
      // 更新父组件的注入pageView对象
      this.resetInjectionTarget()
    },
    updateSpecifyData(res) {
      const list = ["sum"]
      if (res && res.data) {
        list.forEach(key => {
          if (res.data[key] !== undefined) {
            this[key] = res.data[key]
          }
        })
      }
    },

    // 请求 失败回调
    requestFail(err) {
      console.log("请求失败", err)
      this.callFail(err)
      this.triggerEvent("requestFail", err)
    },

    // 取出列表 (根据实际返回结果调整)
    getResponseList(res) {
      const listPathList = this.data.listPath.split(".")
      let newRes = res
      for (let key of listPathList) {
        newRes = newRes[key]
      }
      return newRes
    },

    // 更新组件数据
    updateDate(list, count) {
      //当前页面
      const curPage = this.curPage
      //数据列表数量
      // this.listCount = curPage == 1 ? list.length : this.listCount + list.length
      this.listCount = count
      // 拼接
      this.list = curPage == 1 ? list : [...this.list, ...list]
      this.setData({
        //是否加载中
        isLoading: false,
        isNoMore: list.length < this.data.pageLimit
      })
    },

    // 更新父组件的注入pageView对象
    resetInjectionTarget() {
      const pageViewId = this.id || ""
      const injectionParam = {}
      const parentTarget = getCurrentPages()[getCurrentPages().length - 1]
      const parentTargetInjectionObjectName = this.data.parentTargetInjectionObjectName

      // 注入对象
      if (parentTargetInjectionObjectName) {
        const injectionObject = parentTarget.data[parentTargetInjectionObjectName] ? parentTarget.data[parentTargetInjectionObjectName] : {}
        parentTarget[pageViewId + 'Target'] = this
        injectionObject[pageViewId + 'Target'] = this
        injectionParam[parentTargetInjectionObjectName] = injectionObject
        parentTarget.setData(injectionParam)
      } else {
        parentTarget[pageViewId + 'Target'] = this
        injectionParam[pageViewId + 'Target'] = this
        parentTarget.setData(injectionParam)
      }
    },

    // 功能方法:判断是否函数或者undefined
    isFuntionOrUndefined(fun) {
      return (typeof fun) == 'function' || fun == undefined
    },
  }
})